package com.aliyun.heiyu.powermaster.server.rotary.service.impl;

import com.aliyun.heiyu.powermaster.server.rotary.contants.ModbusOrderContant;
import com.aliyun.heiyu.powermaster.server.rotary.contants.ProtocolContant;
import com.aliyun.heiyu.powermaster.server.rotary.dao.impl.WarnDAOImpl;
import com.aliyun.heiyu.powermaster.server.rotary.object.dto.AirInformationDTO;
import com.aliyun.heiyu.powermaster.server.rotary.object.entity.CoilEntity;
import com.aliyun.heiyu.powermaster.server.rotary.object.transit.ResTem;
import com.aliyun.heiyu.powermaster.server.rotary.object.transit.TemData;
import com.aliyun.heiyu.powermaster.server.rotary.service.AirService;
import com.aliyun.heiyu.powermaster.server.rotary.service.IpcService;
import com.aliyun.heiyu.powermaster.server.rotary.service.WarnService;
import com.aliyun.heiyu.powermaster.server.rotary.task.HeartbeatTask;
import com.aliyun.heiyu.powermaster.server.rotary.task.WarnTask;
import com.aliyun.heiyu.powermaster.server.rotary.utils.IpcDataUtil;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description 告警业务实现类
 * @Author shun.zhang
 * @Date 2020/1/8 17:22
 **/
public class WarnServiceImpl implements WarnService {
    private static Logger logger = LoggerFactory.getLogger(WarnServiceImpl.class);
    public static Map<String,Date> airDate = new HashMap<>();
    private Map<String, CoilEntity> coils;
    IpcService ipcService;
    AirService airService;
    WarnDAOImpl warnDAO;

    public WarnServiceImpl() {
        ipcService = new IpcServiceImpl();
        airService = new AirServiceImpl();
        warnDAO = new WarnDAOImpl();
    }

    public WarnServiceImpl(int count) {
        ipcService = new IpcServiceImpl();
        airService = new AirServiceImpl();
        warnDAO = new WarnDAOImpl();
    }

    /**
     * 空调告警
     **/
    @Override
    public void getAirWarn() {
        /**获取工控机信息*/
        Map<String, String> ipc = AirServiceImpl.ipc;
        if (null == ipc) {
            return;
        }
        //1.在使用的空调获取空调
        List<AirInformationDTO> airs = airService.getAirInformation(null, null);
        logger.info("获取空调的信息:{}", airs);
        //2.发送请求
        if (CollectionUtils.isEmpty(airs)) {
            return;
        }
        for (AirInformationDTO airInformationDTO : airs) {
            if (!airInformationDTO.getDevice_model().equals(AirServiceImpl.device_model)) {
                continue;
            }
            airInformationDTO.setAir_number(1);
            StringBuffer sbu = new StringBuffer();
            /**2.读取数据*/
            String requestModbus = IpcDataUtil.potData(ProtocolContant.MODBUS, airInformationDTO.getAir_number(), ModbusOrderContant.READCOIL, 26, 14);
            sbu.append("http://")
                .append(ipc.get("i_ip"))
                .append(":")
                .append(ipc.get("i_port"))
                .append("/getValue");
            logger.info("空调告警 - 请求路径:{}   发送的命令:{}",sbu.toString(),requestModbus);
            ResTem resTem = ipcService.sendOrderToIpc(sbu.toString(), requestModbus);
            logger.info("空调告警 - 响应的数据:{}", resTem.toString());
            /**3.保存*/
            TemData data = IpcDataUtil.getData(resTem.getData());
            if (null == data) {
                logger.error("编号为:[{}]的空调未获取到数据或者连接异常",airInformationDTO.getAir_number());
                return;
            }
            Map<Integer, Double> values = data.getValue();
            saveWarn(values, airInformationDTO.getDevice_id(), airInformationDTO.getDevice_model());
        }
    }

    /**
     * 心跳监测
     **/
    @Override
    public void heartbeat() {
        //查询工控机信息
        Map<String, String> ipc = airService.queryIpc();
        if (null == ipc) {
            return;
        }
        //1.在使用的空调获取空调
        List<AirInformationDTO> airs = airService.getAirInformation(null, null);
        logger.info("heartbeat 获取空调的信息:"+ airs);
        //2.发送请求
        if (CollectionUtils.isEmpty(airs)) {
            return;
        }
        for (AirInformationDTO airInformationDTO : airs) {
            if (!airInformationDTO.getDevice_model().equals(AirServiceImpl.device_model)) {
                continue;
            }
            airDate.put(airInformationDTO.getDevice_id(),new Date());
            airInformationDTO.setAir_number(1);
            StringBuffer sbu = new StringBuffer();
            /**2.读取数据*/
            String requestModbus = IpcDataUtil.potData(ProtocolContant.MODBUS, airInformationDTO.getAir_number(), ModbusOrderContant.READCOIL, 1, 1);
            sbu.append("http://")
                .append(ipc.get("i_ip"))
                .append(":")
                .append(ipc.get("i_port"))
                .append("/getValue");
            ResTem resTem = ipcService.sendOrderToIpc(sbu.toString(), requestModbus);
            logger.info("heartbeat - 响应数据:"+ resTem.getData());
            /**3.保存*/
            TemData data = IpcDataUtil.getData(resTem.getData());
            if (null == data) {
                logger.error("编号为:["+airInformationDTO.getAir_number()+"]的空调未获取到数据或者连接异常");
                return;
            }
            Map<Integer, Double> values = data.getValue();
            //保存告警信息
            saveHeart(values, airInformationDTO.getAir_number(), airInformationDTO.getDevice_id(), airInformationDTO.getDevice_model());
        }
    }

    public void saveHeart(Map<Integer, Double> values, Integer number, String device_id, String model) {
        //遍历map
        if (values.size() == 0) {
            return;
        }
        for (Integer key : values.keySet()) {
            double value = values.get(key);
            if (value == 1) {
                logger.info("编号为:"+number+"  心跳检测正常");
                continue;
            }
            //心跳异常
            if (value == 0) {
                logger.info("编号为:"+number+"  心跳检测异常");
                if (null == coils) {
                    coils = warnDAO.getCoilsMap();
                }
                logger.info("线圈数据:"+ coils);
                StringBuilder sbu = new StringBuilder();
                sbu.append(model)
                    .append("_")
                    .append(key);
                CoilEntity coilEntity = coils.get(sbu.toString());
                StringBuilder desc = new StringBuilder();
                desc.append("编号为: ")
                    .append(number)
                    .append("  的空调心跳检测异常");
                coilEntity.setDescription(desc.toString());
                if (null == coilEntity) {
                    continue;
                }
                //保存告警信息
                warnDAO.saveWarn(coilEntity, device_id);
                logger.info(desc.toString());
            }
        }
    }

    public void saveWarn(Map<Integer, Double> values, String device_id, String model) {
        //遍历map
        if (values.size() <= 0) {
            return;
        }
        for (Integer key : values.keySet()) {
            double value = values.get(key);
            if (value == 0) {
                continue;
            }
            if (null == coils) {
                coils = warnDAO.getCoilsMap();
            }
            StringBuilder sbu = new StringBuilder();
            sbu.append(model)
                .append("_")
                .append(key);
            CoilEntity coilEntity = coils.get(sbu.toString());
            if (null == coilEntity) {
                continue;
            }
            //保存告警信息
            warnDAO.saveWarn(coilEntity, device_id);
        }
    }

    /**
     * 心跳任务定时器
     **/
    public void heartbeatTask() {
        try {
            //1.创建scheduler，调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //2.定义一个Trigger,触发条件类
            TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();
            triggerBuilder.withIdentity("heartbeat_Data", "heartbeat")
                //一旦加入scheduler，立即生效，即开始时间
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                    //规定时间执行一次（s）
                    .withIntervalInSeconds(5)
                    //一直执行，直到结束时间
                    .repeatForever());
            Trigger trigger = triggerBuilder.build();

            //3.定义一个JobDetail
            //定义Job类为HelloQuartz类，这是真正的执行逻辑所在
            JobDetail job = JobBuilder.newJob(HeartbeatTask.class)
                .withIdentity("heartbeat_data_get", "heartbeatData")
                .usingJobData("heartbeat_data_job", "heartbeat_data")
                .withDescription("心跳检测")
                .build();
            //4.调度器 中加入 任务和触发器
            scheduler.scheduleJob(job, trigger);
            //5.启动任务调度
            scheduler.start();
        } catch (Exception e) {
            logger.error("心跳检测任务执行异常", e);
        }
    }

    /**
     * 获取告警数据定时器
     */
    public void getWarnDataTask() {
        try {
            //1.创建scheduler，调度器
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            //2.定义一个Trigger,触发条件类
            TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();
            triggerBuilder.withIdentity("Warn_Data", "warn")
                //一旦加入scheduler，立即生效，即开始时间
                .startNow()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                    //规定时间执行一次（s）
                    .withIntervalInSeconds(60)
                    //一直执行，直到结束时间
                    .repeatForever());
            Trigger trigger = triggerBuilder.build();

            //3.定义一个JobDetail
            //定义Job类为HelloQuartz类，这是真正的执行逻辑所在
            JobDetail job = JobBuilder.newJob(WarnTask.class)
                .withIdentity("warn_data_get", "warnData")
                .usingJobData("warn_data_job", "warn_data")
                .withDescription("获取告警信息")
                .build();
            //4.调度器 中加入 任务和触发器
            scheduler.scheduleJob(job, trigger);
            //5.启动任务调度
            scheduler.start();
        } catch (Exception e) {
            logger.error("获取告警信息的定时器异常", e);
        }
    }
}
